package com.beauty.product.service.impl;

import com.beauty.product.dto.PageResponse;
import com.beauty.product.dto.ProductAttributeDto;
import com.beauty.product.dto.ProductDto;
import com.beauty.product.dto.ProductImageDto;
import com.beauty.product.dto.ProductQueryParam;
import com.beauty.product.entity.Product;
import com.beauty.product.entity.ProductAttribute;
import com.beauty.product.entity.ProductImage;
import com.beauty.product.repository.CategoryRepository;
import com.beauty.product.repository.ProductAttributeRepository;
import com.beauty.product.repository.ProductImageRepository;
import com.beauty.product.repository.ProductRepository;
import com.beauty.product.service.ProductElasticsearchService;
import com.beauty.product.service.ProductService;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.criteria.Predicate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Slf4j
public class ProductServiceImpl implements ProductService {

    private final ProductRepository productRepository;
    private final ProductImageRepository productImageRepository;
    private final ProductAttributeRepository productAttributeRepository;
    private final ProductElasticsearchService productElasticsearchService;
    private final CategoryRepository categoryRepository;

    @Override
    @Transactional
    public ProductDto createProduct(ProductDto productDto) {
        // 转换商品基本信息
        Product product = productDto.toEntity();
        
        // 如果ID为空，生成格式化的自增ID (PRD001, PRD002, ...)
        if (product.getId() == null || product.getId().trim().isEmpty()) {
            String nextId = generateNextProductId();
            log.info("为新商品生成ID: {}", nextId);
            product.setId(nextId);
        }

        // 确保创建时间设置正确
        if (product.getCreatedTime() == null) {
            product.setCreatedTime(LocalDateTime.now());
        }
        product.setUpdatedTime(LocalDateTime.now());

        // 保存商品
        log.info("保存商品: {}", product.getName());
        Product savedProduct = productRepository.save(product);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(savedProduct.getId());

        return ProductDto.fromEntity(savedProduct);
    }

    /**
     * 生成下一个商品ID，格式为PRDxxx（xxx是从001开始的三位数）
     * @return 下一个商品ID
     */
    private String generateNextProductId() {
        // 查询最大的PRD格式商品ID
        String maxId = productRepository.findMaxProductId();
        
        // 如果没有现有的PRD格式ID，则从PRD001开始
        if (maxId == null || !maxId.startsWith("PRD")) {
            return "PRD001";
        }
        
        try {
            // 提取数字部分
            String numberPart = maxId.substring(3);
            int number = Integer.parseInt(numberPart);
            
            // 生成下一个ID
            return String.format("PRD%03d", number + 1);
        } catch (NumberFormatException e) {
            // 解析错误时从PRD001开始
            log.error("无法解析商品ID: {}", maxId, e);
            return "PRD001";
        }
    }

    @Override
    public ProductDto getProductById(String id) {
        Product product = productRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("商品不存在: " + id));

        ProductDto productDto = ProductDto.fromEntity(product);
        enrichProductDto(productDto);
        return productDto;
    }

    @Override
    public ProductDto getProductBySku(String sku) {
        Product product = productRepository.findBySku(sku)
                .orElseThrow(() -> new EntityNotFoundException("商品不存在: " + sku));

        ProductDto productDto = ProductDto.fromEntity(product);
        enrichProductDto(productDto);
        return productDto;
    }

    @Override
    public Page<ProductDto> getProducts(ProductQueryParam param) {
        PageRequest pageRequest = PageRequest.of(
                param.getPageNum() - 1,
                param.getPageSize(),
                Sort.Direction.fromString(param.getSortDirection()),
                param.getSortBy()
        );

        Specification<Product> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 关键词搜索
            if (StringUtils.hasText(param.getKeyword())) {
                String keyword = "%" + param.getKeyword() + "%";
                predicates.add(cb.or(
                        cb.like(root.get("name"), keyword),
                        cb.like(root.get("description"), keyword),
                        cb.like(root.get("brand"), keyword)
                ));
            }

            // 分类过滤
            if (param.getCategoryId() != null) {
                predicates.add(cb.equal(root.get("categoryId"), param.getCategoryId()));
            }

            // 品牌过滤
            if (StringUtils.hasText(param.getBrand())) {
                predicates.add(cb.equal(root.get("brand"), param.getBrand()));
            }

            // 状态过滤
            if (param.getIsPublished() != null) {
                predicates.add(cb.equal(root.get("isPublished"), param.getIsPublished()));
            }
            if (param.getIsRecommended() != null) {
                predicates.add(cb.equal(root.get("isRecommended"), param.getIsRecommended()));
            }
            if (param.getIsNew() != null) {
                predicates.add(cb.equal(root.get("isNew"), param.getIsNew()));
            }
            if (param.getIsHot() != null) {
                predicates.add(cb.equal(root.get("isHot"), param.getIsHot()));
            }

            // 价格范围过滤
            if (param.getMinPrice() != null) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("price"), param.getMinPrice()));
            }
            if (param.getMaxPrice() != null) {
                predicates.add(cb.lessThanOrEqualTo(root.get("price"), param.getMaxPrice()));
            }

            return cb.and(predicates.toArray(new Predicate[0]));
        };

        Page<Product> productPage = productRepository.findAll(spec, pageRequest);
        return productPage.map(product -> {
            ProductDto productDto = ProductDto.fromEntity(product);
            enrichProductDto(productDto);
            return productDto;
        });
    }

    @Override
    public Page<ProductDto> getProductsByCategory(Long categoryId, int pageNum, int pageSize) {
        PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize);
        Page<Product> productPage = productRepository.findByCategoryId(categoryId, pageRequest);
        return productPage.map(product -> {
            ProductDto productDto = ProductDto.fromEntity(product);
            enrichProductDto(productDto);
            return productDto;
        });
    }

    @Override
    public List<ProductDto> getHotProducts(int limit) {
        PageRequest pageRequest = PageRequest.of(0, limit);
        Page<Product> productPage = productRepository.findByIsHot(true, pageRequest);
        return productPage.getContent().stream()
                .map(product -> {
                    ProductDto productDto = ProductDto.fromEntity(product);
                    enrichProductDto(productDto);
                    return productDto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductDto> getNewProducts(int limit) {
        PageRequest pageRequest = PageRequest.of(0, limit);
        Page<Product> productPage = productRepository.findByIsNew(true, pageRequest);
        return productPage.getContent().stream()
                .map(product -> {
                    ProductDto productDto = ProductDto.fromEntity(product);
                    enrichProductDto(productDto);
                    return productDto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductDto> getRecommendedProducts(int limit) {
        PageRequest pageRequest = PageRequest.of(0, limit);
        Page<Product> productPage = productRepository.findByIsRecommended(true, pageRequest);
        return productPage.getContent().stream()
                .map(product -> {
                    ProductDto productDto = ProductDto.fromEntity(product);
                    enrichProductDto(productDto);
                    return productDto;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public ProductDto updateProduct(String id, ProductDto productDto) {
        // 检查商品是否存在
        Product existingProduct = productRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("商品不存在: " + id));

        // 更新商品基本信息
        existingProduct.setName(productDto.getName());
        existingProduct.setSku(productDto.getSku());
        existingProduct.setPrice(productDto.getPrice());
        existingProduct.setOriginalPrice(productDto.getOriginalPrice());
        existingProduct.setCategoryId(productDto.getCategoryId());
        existingProduct.setBrand(productDto.getBrand());
        existingProduct.setDescription(productDto.getDescription());
        existingProduct.setCoverImage(productDto.getCoverImage());
        existingProduct.setIsPublished(productDto.getIsPublished());
        existingProduct.setIsRecommended(productDto.getIsRecommended());
        existingProduct.setIsNew(productDto.getIsNew());
        existingProduct.setIsHot(productDto.getIsHot());
        existingProduct.setSort(productDto.getSort());
        existingProduct.setUpdatedTime(java.time.LocalDateTime.now());

        // 保存更新
        Product updatedProduct = productRepository.save(existingProduct);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(updatedProduct.getId());

        return ProductDto.fromEntity(updatedProduct);
    }

    @Override
    @Transactional
    public void deleteProduct(String id) {
        // 检查商品是否存在
        if (!productRepository.existsById(id)) {
            throw new EntityNotFoundException("商品不存在: " + id);
        }

        // 删除商品图片和属性
        List<ProductImage> images = productImageRepository.findByProductId(id);
        if (!images.isEmpty()) {
            productImageRepository.deleteAll(images);
        }

        List<ProductAttribute> attributes = productAttributeRepository.findByProductId(id);
        if (!attributes.isEmpty()) {
            productAttributeRepository.deleteAll(attributes);
        }

        // 删除商品
        productRepository.deleteById(id);

        // 删除Elasticsearch中的数据
        productElasticsearchService.deleteById(id);
    }

    @Override
    @Transactional
    public void publishProduct(String id, Boolean isPublished) {
        Product product = productRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("商品不存在: " + id));
        product.setIsPublished(isPublished);
        productRepository.save(product);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(id);
    }

    @Override
    @Transactional
    public ProductImageDto addProductImage(String productId, ProductImageDto imageDto) {
        // 检查商品是否存在
        if (!productRepository.existsById(productId)) {
            throw new EntityNotFoundException("商品不存在: " + productId);
        }

        ProductImage image = imageDto.toEntity();
        image.setProductId(productId);
        ProductImage savedImage = productImageRepository.save(image);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(productId);

        return ProductImageDto.fromEntity(savedImage);
    }

    @Override
    public List<ProductImageDto> getProductImages(String productId) {
        List<ProductImage> images = productImageRepository.findByProductId(productId);
        return images.stream().map(ProductImageDto::fromEntity).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void deleteProductImage(Long imageId) {
        if (!productImageRepository.existsById(imageId)) {
            throw new EntityNotFoundException("商品图片不存在: " + imageId);
        }
        ProductImage image = productImageRepository.findById(imageId)
                .orElseThrow(() -> new EntityNotFoundException("商品图片不存在: " + imageId));
        String productId = image.getProductId();
        productImageRepository.delete(image);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(productId);
    }

    @Override
    @Transactional
    public ProductAttributeDto addProductAttribute(String productId, ProductAttributeDto attributeDto) {
        // 检查商品是否存在
        if (!productRepository.existsById(productId)) {
            throw new EntityNotFoundException("商品不存在: " + productId);
        }

        ProductAttribute attribute = attributeDto.toEntity();
        attribute.setProductId(productId);
        ProductAttribute savedAttribute = productAttributeRepository.save(attribute);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(productId);

        return ProductAttributeDto.fromEntity(savedAttribute);
    }

    @Override
    public List<ProductAttributeDto> getProductAttributes(String productId) {
        List<ProductAttribute> attributes = productAttributeRepository.findByProductId(productId);
        return attributes.stream().map(ProductAttributeDto::fromEntity).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void deleteProductAttribute(Long attributeId) {
        ProductAttribute attribute = productAttributeRepository.findById(attributeId)
                .orElseThrow(() -> new EntityNotFoundException("商品属性不存在: " + attributeId));
        String productId = attribute.getProductId();
        productAttributeRepository.delete(attribute);

        // 同步到Elasticsearch
        productElasticsearchService.syncProductFromDB(productId);
    }

    @Override
    public PageResponse<ProductDto> searchProducts(String keyword, Pageable pageable) {
        // 使用ES进行搜索
        return productElasticsearchService.search(keyword, pageable);
    }

    @Override
    public PageResponse<ProductDto> advancedSearch(String name, String sku, String brand, String description, Pageable pageable) {
        // 使用ES进行高级搜索
        return productElasticsearchService.advancedSearch(name, brand, description, null, null, null, null, null, null, null, pageable);
    }

    @Override
    public PageResponse<ProductDto> getProductsPage(Pageable pageable) {
        Page<Product> page = productRepository.findAll(pageable);
        Page<ProductDto> dtoPage = page.map(product -> {
            ProductDto productDto = ProductDto.fromEntity(product);
            enrichProductDto(productDto);
            return productDto;
        });

        return PageResponse.fromPage(dtoPage);
    }

    @Override
    public ProductImageDto getProductImage(Long imageId) {
        ProductImage image = productImageRepository.findById(imageId)
                .orElseThrow(() -> new EntityNotFoundException("图片不存在: " + imageId));
        return ProductImageDto.fromEntity(image);
    }

    @Override
    @Transactional
    public ProductImageDto updateProductImage(ProductImageDto imageDto) {
        if (imageDto.getId() == null) {
            throw new IllegalArgumentException("更新图片时必须提供ID");
        }

        ProductImage image = productImageRepository.findById(imageDto.getId())
                .orElseThrow(() -> new EntityNotFoundException("图片不存在: " + imageDto.getId()));

        // 更新图片信息
        image.setUrl(imageDto.getImageUrl());
        image.setIsCover(imageDto.isMain());
        image.setIsMain(imageDto.isMain());
        image.setSort(imageDto.getSort());

        // 保存更新
        image = productImageRepository.save(image);

        return ProductImageDto.fromEntity(image);
    }

    private void enrichProductDto(ProductDto productDto) {
        String productId = productDto.getId();

        // 加载商品图片
        List<ProductImage> images = productImageRepository.findByProductId(productId);
        productDto.setImages(images.stream()
                .map(ProductImageDto::fromEntity)
                .collect(Collectors.toList()));

        // 加载商品属性
        List<ProductAttribute> attributes = productAttributeRepository.findByProductId(productId);
        productDto.setAttributes(attributes.stream()
                .map(ProductAttributeDto::fromEntity)
                .collect(Collectors.toList()));

        // 加载分类名称
        if (productDto.getCategoryId() != null) {
            categoryRepository.findById(productDto.getCategoryId())
                .ifPresent(category -> {
                    log.info("为商品 {} 设置分类名称: {}", productDto.getId(), category.getName());
                    productDto.setCategoryName(category.getName());
                });
        }
    }
}
